package com.glkj.vipsystem.modules.member.controller;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.glkj.vipsystem.common.exception.BizException;
import com.glkj.vipsystem.common.utils.Constant;
import com.glkj.vipsystem.common.utils.PageUtils;
import com.glkj.vipsystem.common.utils.Query;
import com.glkj.vipsystem.common.utils.R;
import com.glkj.vipsystem.common.validator.ValidatorUtils;
import com.glkj.vipsystem.common.validator.group.AddGroup;
import com.glkj.vipsystem.common.validator.group.UpdateGroup;
import com.glkj.vipsystem.entity.ao.*;
import com.glkj.vipsystem.modules.member.entity.VipCardExcelEntity;
import com.glkj.vipsystem.modules.sys.controller.AbstractController;
import com.glkj.vipsystem.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.*;

/**
 * 会员卡控制器
 *
 * @author LiMuchan
 */
@RestController
@RequestMapping("/member/vipCard")
public class VipCardController extends AbstractController {

    @Resource
    private IVipCardService vipCardService;
    @Resource
    private ICompanyService companyService;
    @Resource
    private IMemberService memberService;
    @Resource
    private IVipCardRuleService vipCardRuleService;
    @Resource
    private IShopService shopService;
    @Resource
    private IEmployeeService employeeService;

    /**
     * 列表
     */
    @RequestMapping(value = "/list")
    @RequiresPermissions(value = {"member:vipCard:list", "cash:order:list"}, logical = Logical.OR)
    public R list(@RequestParam Map<String, Object> params) {
        String companyId = (String) params.get("companyId"); // 所属公司筛选
        String shopId = (String) params.get("shopId"); // 开卡店铺筛选
        String cardNo = (String) params.get("cardNo"); // 会员卡号搜索
        String memberInfo = (String) params.get("memberInfo"); // 会员姓名/电话搜索
        String cardType = (String) params.get("cardType"); // 卡类型搜索
        String cash = (String) params.get("cash"); // 查找会员

        Wrapper<VipCardAO> wrapper = new EntityWrapper<VipCardAO>();
        wrapper.orderBy("id desc");
        wrapper.setSqlSelect("*,(select company_name from t_company where id = t_vip_card.company_id) as company_name" +
                ",(select shop_name from t_shop where id = t_vip_card.shop_id) as shop_name");

        // 数据权限控制
        if (isCompanyRole()) {
            // 公司管理员
            String username = getUser().getUsername();
            wrapper.where("company_id = (select id from t_company where `username` = '" + username + "')");
        } else if (StringUtils.isBlank(cash) && isEmployeeRole()) {
            // 员工
            String username = getUser().getUsername();
            wrapper.where("shop_id = (select shop_id from t_employee where `username` = '" + username + "')");
        }
        if (StringUtils.isNotBlank(companyId)) {
            wrapper.eq("company_id", companyId);
        }
        if (!isEmployeeRole() && StringUtils.isNotBlank(shopId)) {
            wrapper.eq("shop_id", shopId);
        }
        if (StringUtils.isNotBlank(cardNo)) {
            wrapper.like("card_no", cardNo);
        }
        if (StringUtils.isNotBlank(memberInfo)) {
            wrapper.where("(member_name like '%" + memberInfo + "%' or member_mobile like '%" + memberInfo + "%')");
        }
        if (StringUtils.isNotBlank(cardType)) {
            wrapper.eq("card_type", cardType);
        }
        Page<VipCardAO> page = vipCardService.selectPage(
                new Query<VipCardAO>(params).getPage(), wrapper
        );
        return R.ok().put("page", new PageUtils(page));
    }

    /**
     * 根据会员码查询会员
     */
    @RequestMapping(value = "/getByNo")
    @RequiresPermissions(value = {"cash:order:list"})
    public R getByNo(@RequestParam Map<String, Object> params) {
        String cardNo = (String) params.get("cardNo"); // 会员卡号搜索
        if (StringUtils.isBlank(cardNo)) {
            return R.error("会员卡号空");
        }
        Wrapper<VipCardAO> wrapper = new EntityWrapper<>();
        wrapper.orderBy("id desc");

        wrapper.eq("card_no", cardNo);

        VipCardAO vipCard = vipCardService.selectOne(
                wrapper
        );
        return R.ok().put("data", vipCard);
    }

    /**
     * 获取今天过生日的会员
     */
    @RequestMapping(value = "/getTodayBirthDayMember")
    public R getTodayBirthDayMember() {
        Wrapper<VipCardAO> wrapper = new EntityWrapper<>();
        wrapper.where("MONTH(birthday) = MONTH(NOW()) and DAY(birthday) = DAY(NOW())");
        String username = getUser().getUsername();
        // 角色判断
        if (isCompanyRole()) {
            // 公司管理员
            wrapper.where("company_id = (select id from t_company where `username` = '" + username + "')");
        } else if (isEmployeeRole()) {
            wrapper.where("shop_id = (select shop_id from t_employee where `username` = '" + username + "')");
        }
        List<VipCardAO> list = vipCardService.selectList(wrapper);

        return R.ok().put("data", list);
    }

    /**
     * 详情
     */
    @RequestMapping(value = "/detail/{id}")
    @RequiresPermissions({"member:vipCard:list"})
    public R detail(@PathVariable("id") Integer id) {
        VipCardAO vipCardAO = vipCardService.selectById(id);
        if (vipCardAO == null) {
            return R.error("会员卡不存在");
        }
        CompanyAO companyAO = companyService.selectById(vipCardAO.getCompanyId());
        if (companyAO != null) {
            vipCardAO.setCompanyName(companyAO.getCompanyName());
        }
        return R.ok().put("item", vipCardAO);
    }

    /**
     * 保存新增
     */
    @RequestMapping(value = "/save")
    @RequiresPermissions({"member:vipCard:save"})
    public R save(@RequestBody VipCardAO vipCard) {
        ValidatorUtils.validateEntity(vipCard);
        CompanyAO companyAO = companyService.selectById(vipCard.getCompanyId());
        if (companyAO == null || companyAO.getStatus() != 1) {
            return R.error("开卡公司不存在或已禁用");
        }
        ShopAO shopAO = shopService.selectById(vipCard.getShopId());
        if (shopAO == null || shopAO.getStatus() != 1) {
            return R.error("开卡店铺不存在或已禁用");
        }
        MemberAO memberAO = memberService.selectByMobile(vipCard.getMemberMobile());
        if (memberAO != null) {
            vipCard.setMemberId(memberAO.getId());
        }
        // 卡类型校验
        Integer cardType = vipCard.getCardType();
        if (cardType == Constant.VipCardType.CIKA.getValue()) {
            // 次卡
            Integer cardTimesType = vipCard.getCardTimesType();
            if (cardTimesType == 1 && (vipCard.getCardTimes() == null || vipCard.getCardTimes() <= 0)) {
                return R.error("请输入正确的有效次数");
            } else if (cardTimesType == 0) {
                vipCard.setCardTimes(0);
            }
            if (vipCard.getExpireTime() == null || vipCard.getExpireTime().before(new Date())) {
                return R.error("请选择正确的有效期");
            }
        } else if (cardType == Constant.VipCardType.CHONGZHIKA.getValue()) {
            // 充值卡
            if (vipCard.getCardBalance() == null ||
                    vipCard.getCardBalance().compareTo(new BigDecimal("0")) <= 0) {
                return R.error("请输入正确的卡金额");
            }
        } else if (cardType == Constant.VipCardType.JIFENKA.getValue()) {
            if (vipCard.getCardPoints() == null || vipCard.getCardPoints() <= 0) {
                return R.error("请输入正确的赠送积分");
            }
        } else {
            // 不是这三种卡 错误
            return R.error("请选择正确的开卡类型");
        }
        vipCard.setCardNo(generateVipCardNo(cardType));
        vipCard.setCreateTime(new Date());
        try {
            String operator = getUser().getUsername();
            if (isCompanyRole()) {
                // 公司管理员
                CompanyAO loginUserCompany = companyService.selectOne(
                        new EntityWrapper<CompanyAO>().eq("username", getUser().getUsername())
                );
                if (loginUserCompany != null) {
                    operator = loginUserCompany.getManagerName() + " " + loginUserCompany.getManagerMobile();
                }
            }
            vipCardService.save(vipCard, operator);
        } catch (DuplicateKeyException e) {
            return R.error(String.format("该用户在公司[%s]已有卡[%s]", companyAO.getCompanyName(), Constant.VipCardType.valueOf(cardType)));
        }
        return R.ok();
    }

    /**
     * 批量导入
     */
//    @PostMapping("/import")
//    @RequiresPermissions("member:vipCard:import")
    public R importVipCards(@RequestParam("file") MultipartFile file, Integer companyId, Integer shopId) throws Exception {
        if (file.isEmpty()) {
            throw new BizException("请选择文件");
        }
        if (companyId == null) {
            return R.error("请选择公司");
        }
        if (shopId == null) {
            return R.error("请选择开卡店铺");
        }
        CompanyAO companyAO = companyService.selectById(companyId);
        if (companyAO == null || companyAO.getStatus() != 1) {
            return R.error("开卡公司不存在或已禁用");
        }
        ShopAO shopAO = shopService.selectById(shopId);
        if (shopAO == null || shopAO.getStatus() != 1) {
            return R.error("开卡店铺不存在或已禁用");
        }
        boolean xlsx = ExcelUtil.isXlsx(file.getInputStream());
        if (!xlsx) {
            return R.error("请使用下载的模板");
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(0);
        params.setHeadRows(1);
        List<VipCardExcelEntity> list;
        try {
            list = ExcelImportUtil.importExcel(file.getInputStream(), VipCardExcelEntity.class, params);
        } catch (Exception e) {
            return R.error(e.getMessage());
        }
        if (CollectionUtils.isEmpty(list)) {
            return R.error("请填写数据");
        }

        String operator = getUser().getUsername();
        if (isCompanyRole()) {
            // 公司管理员
            CompanyAO loginUserCompany = companyService.selectOne(
                    new EntityWrapper<CompanyAO>().eq("username", getUser().getUsername())
            );
            if (loginUserCompany != null) {
                operator = loginUserCompany.getManagerName() + " " + loginUserCompany.getManagerMobile();
            }
        }

        // 数据校验
        StringBuilder sbErr = new StringBuilder();
        List<VipCardAO> cardAOS = new ArrayList<>();
        List<String> cardNos = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            VipCardExcelEntity entity = list.get(i);
            VipCardAO vipCard = new VipCardAO();
            Integer cardType = entity.getCardType();
            String value = entity.getValue();
            vipCard.setCardType(cardType);
            if (null == cardType) {
                // 不是这三种卡 错误
                sbErr.append("第").append(i + 1).append("行，请选择正确的卡类型").append("<br>");
            } else if (cardType == Constant.VipCardType.CIKA.getValue()) {
                // 次卡
                Integer cardTimesType = entity.getCardTimesType();
                if (null == cardTimesType) {
                    sbErr.append("第").append(i + 1).append("行，请选择是否限制次数").append("<br>");
                } else if (1 == cardTimesType) {
                    if (StringUtils.isBlank(value) || !NumberUtil.isInteger(value)
                            || Integer.valueOf(value) <= 0) {
                        sbErr.append("第").append(i + 1).append("行次数错误").append("<br>");
                    } else {
                        vipCard.setCardTimes(Integer.valueOf(value));
                    }
                } else if (0 == cardTimesType) {
                    vipCard.setCardTimes(0);
                } else {
                    sbErr.append("第").append(i + 1).append("行，请选择是否限制次数").append("<br>");
                }
                if (entity.getExpireTime() == null || entity.getExpireTime().before(new Date())) {
                    sbErr.append("第").append(i + 1).append("行，请输入正确的有效期").append("<br>");
                } else {
                    vipCard.setExpireTime(entity.getExpireTime());
                }
                vipCard.setCardTimesType(cardTimesType);
                vipCard.setCardNo(generateVipCardNo(cardType, cardNos));
            } else if (cardType == Constant.VipCardType.CHONGZHIKA.getValue()) {
                // 充值卡
                if (StringUtils.isBlank(value) || !NumberUtil.isNumber(value) ||
                        new BigDecimal(value).compareTo(new BigDecimal("0")) <= 0) {
                    sbErr.append("第").append(i + 1).append("行，余额错误").append("<br>");
                } else {
                    vipCard.setCardBalance(new BigDecimal(value).setScale(2, BigDecimal.ROUND_DOWN));
                }
                vipCard.setCardNo(generateVipCardNo(cardType, cardNos));
            } else if (cardType == Constant.VipCardType.JIFENKA.getValue()) {
                if (StringUtils.isBlank(value) || !NumberUtil.isInteger(value) ||
                        Integer.valueOf(value) <= 0) {
                    sbErr.append("第").append(i + 1).append("行，积分错误").append("<br>");
                } else {
                    vipCard.setCardPoints(Integer.valueOf(value));
                }
                vipCard.setCardNo(generateVipCardNo(cardType, cardNos));
            } else {
                // 不是这三种卡 错误
                sbErr.append("第").append(i + 1).append("行，请选择正确的卡类型").append("<br>");
            }

            // 用户姓名校验
            if (StringUtils.isBlank(entity.getMemberName())) {
                sbErr.append("第").append(i + 1).append("行，请填写用户姓名").append("<br>");
            } else {
                vipCard.setMemberName(entity.getMemberName());
            }
            if (StringUtils.isBlank(entity.getMemberMobile())) {
                sbErr.append("第").append(i + 1).append("行，请填写用户电话").append("<br>");
            } else {
                vipCard.setMemberMobile(entity.getMemberMobile());
            }
            String cardFee = entity.getCardFee();
            if (StringUtils.isBlank(cardFee) || !NumberUtil.isNumber(cardFee)
                    || new BigDecimal(cardFee).compareTo(new BigDecimal("0")) <= 0) {
                sbErr.append("第").append(i + 1).append("行，开卡费用错误").append("<br>");
            } else {
                vipCard.setCardFee(new BigDecimal(cardFee));
            }
            MemberAO memberAO = memberService.selectByMobile(vipCard.getMemberMobile());
            if (memberAO != null) {
                vipCard.setMemberId(memberAO.getId());
            }

            vipCard.setCreateTime(new Date());
            vipCard.setCompanyId(companyId);
            vipCard.setShopId(shopId);
            // 校验卡是否重复
            int selectCount = vipCardService.selectCount(
                    new EntityWrapper<VipCardAO>()
                            .eq("company_id", companyId)
                            .eq("card_type", vipCard.getCardType())
                            .eq("member_mobile", vipCard.getMemberMobile())
            );
            if (selectCount > 0) {
                sbErr.append("第").append(i + 1).append("行，用户已有该卡").append("<br>");
            }
            cardAOS.add(vipCard);
        }
        String errMsg = sbErr.toString();
        if (StringUtils.isNotBlank(errMsg)) {
            return R.error(errMsg);
        }
        // 插入
        vipCardService.saveBatch(cardAOS, operator);
        return R.ok();
    }

    /**
     * 下载模板
     */
    @RequestMapping("/template")
    public void template(HttpServletResponse response) throws IOException {
        response.setHeader("content-type", "application/octet-stream");
        response.setHeader("Content-Transfer-Encoding", "binary");
        response.setContentType("application/octet-stream;charset=utf-8");
        response.addHeader("Content-Disposition", "attachment;filename=\"template.xlsx\";");

        //好了 ，现在通过IO流来传送数据
        InputStream input = ClassLoader.getSystemResourceAsStream("template.xlsx");
        OutputStream output = response.getOutputStream();
        byte[] buff = new byte[1024 * 10];//可以自己 指定缓冲区的大小
        int len = 0;
        while ((len = input.read(buff)) > -1) {
            output.write(buff, 0, len);
        }
        //关闭输入输出流
        input.close();
        output.close();
    }

    /**
     * 修改
     */
    @RequestMapping(value = "/update")
    @RequiresPermissions({"member:vipCard:update"})
    public R update(@RequestBody VipCardAO vipCard) {
        VipCardAO selectById = vipCardService.selectById(vipCard.getId());
        if (selectById == null) {
            return R.error("请选择要调整的会员卡");
        }
        if (vipCard.getCardFee() == null) {
            vipCard.setCardFee(new BigDecimal("0"));
        }
        if (vipCard.getCardFee().compareTo(new BigDecimal("0")) < 0) {
            return R.error("请正确输入附加费用");
        }
        String operator = getUser().getUsername();
        if (isCompanyRole()) {
            // 公司管理员
            CompanyAO loginUserCompany = companyService.selectOne(
                    new EntityWrapper<CompanyAO>().eq("username", getUser().getUsername()));
            if (loginUserCompany != null) {
                operator = loginUserCompany.getManagerName() + " " + loginUserCompany.getManagerMobile();
            }
        }
        vipCardService.update(vipCard, operator);
        return R.ok();
    }

    /**
     * 获取操作员信息
     *
     * @return 操作员信息
     */
    private String getOperator() {
        String username = getUser().getUsername();
        if (isCompanyRole()) {
            // 公司管理员
            CompanyAO companyAO = companyService.selectOne(new EntityWrapper<CompanyAO>().eq("username", username));
            if (companyAO != null) {
                username = companyAO.getManagerName() + "-" + companyAO.getManagerMobile();
            }
        } else if (isEmployeeRole()) {
            EmployeeAO employeeAO = employeeService.selectByUsername(username);
            if (employeeAO != null) {
                username = employeeAO.getEmployeeName() + "-" + employeeAO.getEmployeeMobile();
            }
        }
        return username;
    }

    /**
     * 删除
     */
    @RequestMapping(value = "/delete")
    @RequiresPermissions({"member:vipCard:delete"})
    public R delete(@RequestBody Integer[] ids) {
        if (ids != null && ids.length > 0) {
            vipCardService.deleteBatch(Arrays.asList(ids), getOperator());
        }
        return R.ok();
    }

    /**
     * 获取公司卡规则
     */
    @RequestMapping(value = "/rule/detail/{companyId}")
    @RequiresPermissions(value = {"member:vipCard:settings", "cash:order:list"}, logical = Logical.OR)
    public R ruleDetail(@PathVariable("companyId") Integer companyId) {
        VipCardRuleAO item = new VipCardRuleAO();
        if (companyId != null) {
            VipCardRuleAO selectOne = vipCardRuleService.selectOne(new EntityWrapper<VipCardRuleAO>().eq("company_id", companyId));
            if (selectOne != null) {
                item = selectOne;
            }
        }
        return R.ok().put("item", item);
    }

    /**
     * 公司卡规则新增
     */
    @RequestMapping(value = "/rule/save")
    @RequiresPermissions({"member:vipCard:settings"})
    public R ruleSave(@RequestBody VipCardRuleAO vipCardRule) {
        ValidatorUtils.validateEntity(vipCardRule, AddGroup.class);
        String message = validRuleAmount(vipCardRule);
        if (message != null) {
            return R.error(message);
        }
        CompanyAO companyAO = companyService.selectById(vipCardRule.getCompanyId());
        if (companyAO == null) {
            return R.error("公司不存在");
        }
        try {
            vipCardRuleService.insert(vipCardRule);
        } catch (DuplicateKeyException e) {
            return R.error("该公司卡规则已设置");
        }
        return R.ok();
    }

    /**
     * 公司卡规则修改
     */
    @RequestMapping(value = "/rule/update")
    @RequiresPermissions({"member:vipCard:settings"})
    public R ruleUpdate(@RequestBody VipCardRuleAO vipCardRule) {
        ValidatorUtils.validateEntity(vipCardRule, UpdateGroup.class);
        String message = validRuleAmount(vipCardRule);
        if (message != null) {
            return R.error(message);
        }
        vipCardRule.setCompanyId(null);
        vipCardRuleService.updateById(vipCardRule);
        return R.ok();
    }

    /**
     * 生成会员卡号：生成规则：次卡81开头,充值卡82开头,积分卡83开头
     *
     * @param cardType 卡类型
     * @return 会员卡号
     */
    private String generateVipCardNo(Integer cardType) {
        String cardNo = "";
        switch (cardType) {
            case 1:
                cardNo = "81";
                break;
            case 2:
                cardNo = "82";
                break;
            case 3:
                cardNo = "83";
                break;
        }
        while (true) {
            cardNo += DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomNumbers(2);
            int selectCount = vipCardService.selectCount(
                    new EntityWrapper<VipCardAO>()
                            .eq("card_no", cardNo)
            );
            if (selectCount == 0) {
                break;
            }
        }
        return cardNo;
    }

    private String generateVipCardNo(Integer cardType, List<String> cardNos) {
        String cardNo = "";
        switch (cardType) {
            case 1:
                cardNo = "81";
                break;
            case 2:
                cardNo = "82";
                break;
            case 3:
                cardNo = "83";
                break;
        }
        while (true) {
            cardNo += DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomNumbers(2);
            int selectCount = vipCardService.selectCount(
                    new EntityWrapper<VipCardAO>()
                            .eq("card_no", cardNo)
            );
            if (selectCount == 0 && !cardNos.contains(cardNo)) {
                break;
            }
        }
        cardNos.add(cardNo);
        return cardNo;
    }

    /**
     * 校验卡规则金额格式
     */
    private String validRuleAmount(VipCardRuleAO vipCardRule) {
        if (vipCardRule == null) {
            return "数据错误";
        }
        StringBuilder sb = new StringBuilder();
        String pointsAmount = vipCardRule.getPointsAmount();
        String giveAmount = vipCardRule.getGiveAmount();
        if (!NumberUtil.isNumber(pointsAmount) ||
                NumberUtil.isLessOrEqual(new BigDecimal(pointsAmount), new BigDecimal("0"))) {
            sb.append("请输入大于0的积分抵扣金额<br>");
        } else {
            vipCardRule.setPointsAmount(new BigDecimal(pointsAmount).toPlainString());
        }
        vipCardRule.setGiveAmount("0");
//        if (!NumberUtil.isNumber(giveAmount) ||
//                NumberUtil.isLess(new BigDecimal(giveAmount), new BigDecimal("0"))) {
//            sb.append("请正确输入充值赠送金额<br>");
//        } else {
//            vipCardRule.setGiveAmount(new BigDecimal(giveAmount).toPlainString());
//        }
        return StringUtils.isNotBlank(sb.toString()) ? sb.toString() : null;
    }
}
